home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2003 July / CD 2 Debian 3.0r1 / Debian.iso / isolinux / root.bin / root / usr / lib / debootstrap / functions < prev    next >
Encoding:
Text File  |  2002-03-14  |  13.4 KB  |  561 lines

  1.  
  2. ############################################################### smallutils
  3.  
  4. smallyes() {
  5.   YES="${1-y}"
  6.   while true ; do echo "$YES" ; done
  7. }
  8.  
  9. ############################################################### interaction
  10.  
  11. error () {
  12.   if [ "$USE_BOOTFLOPPIES_INTERACTION" ]; then
  13.     echo "E: $2" >&3
  14.   else
  15.     echo "E: $2" >&2
  16.   fi
  17.   exit $1
  18. }
  19.  
  20. warning () {
  21.   if [ "$USE_BOOTFLOPPIES_INTERACTION" ]; then
  22.     echo "W: $1" >&3
  23.   else
  24.     echo "W: $1" >&2
  25.   fi
  26. }
  27.  
  28. info () {
  29.   if [ "$USE_BOOTFLOPPIES_INTERACTION" ]; then
  30.     echo "I: $1" >&3
  31.   else
  32.     echo "I: $1"
  33.   fi
  34. }
  35.  
  36. PROGRESS_NOW=0
  37. PROGRESS_END=0
  38. PROGRESS_NEXT=""
  39. PROGRESS_WHAT=""
  40.  
  41. progress_next () {
  42.   PROGRESS_NEXT="$1"
  43. }
  44.  
  45. wgetprogress () {
  46.   [ ! "$verbose" ] && QSWITCH="-q"
  47.   local ret=0
  48.   if [ "$USE_BOOTFLOPPIES_INTERACTION" -a "$PROGRESS_NEXT" ]; then
  49.     wget "$@" 2>&1 >/dev/null | $PKGDETAILS "WGET%" $PROGRESS_NOW $PROGRESS_NEXT $PROGRESS_END "$PROGRESS_WHAT" >&3
  50.     ret=$?
  51.   else
  52.     wget $QSWITCH "$@"
  53.     ret=$?
  54.   fi
  55.   return $ret
  56. }
  57.  
  58. progress () {
  59.   if [ "$USE_BOOTFLOPPIES_INTERACTION" ]; then
  60.     PROGRESS_NOW="$1"
  61.     PROGRESS_END="$2"
  62.     PROGRESS_WHAT="$3"
  63.     PROGRESS_NEXT=""
  64.     echo "P: $1 $2 $3" >&3
  65.   fi
  66. }
  67.  
  68. ############################################################# set variables
  69.  
  70. download_style () {
  71.   case "$1" in
  72.     "apt")
  73.       if [ "$2" = "var-state" ]; then
  74.     APTSTATE=var/state/apt
  75.       else
  76.         APTSTATE=var/lib/apt
  77.       fi
  78.       DLDEST=apt_dest
  79.       DEBFOR=apt_debfor
  80.       export APTSTATE DLDEST DEBFOR
  81.       ;;
  82.     *)
  83.       error 1 "unknown download style"
  84.       ;;
  85.   esac
  86. }
  87.  
  88. ################################################# work out names for things
  89.  
  90. mirror_style () {
  91.   case "$1" in
  92.     "release")
  93.       DOWNLOAD_DEBS=download_release
  94.       ;;
  95.     "main")
  96.       DOWNLOAD_DEBS=download_main
  97.       ;;
  98.     *)
  99.       error 1 "unknown mirror style"
  100.       ;;
  101.   esac
  102.   export DOWNLOAD_DEBS
  103. }
  104.  
  105. check_md5 () {
  106.   # args: dest md5 size
  107.   local expmd5="$2"
  108.   local expsize="$3"
  109.   relmd5=`md5sum < "$1" | sed 's/ .*$//'`
  110.   relsize=`wc -c < "$1"`
  111.   if [ "$expsize" -ne "$relsize" -o "$expmd5" != "$relmd5" ]; then
  112.     return 1
  113.   fi
  114.   return 0
  115. }
  116.  
  117. get () {
  118.   # args: from dest [md5sum size] [alt {md5sum size type}]
  119.   if [ -e "$2" ]; then
  120.     info "Validating $2"
  121.     if [ "$3" = "" ] || check_md5 $2 $3 $4; then
  122.       return 0
  123.     else
  124.       rm -f "$2"
  125.     fi
  126.   fi
  127.   if [ "$#" -gt 5 ]; then
  128.     local st=3
  129.     if [ "$5" = "-" ]; then st=6; fi
  130.     local order="$(a=$st; while [ "$a" -le $# ]; do eval echo \"\$$(($a+1))\" $a;
  131.                   a=$(($a + 3)); done | sort -n | sed 's/.* //')"
  132.   else
  133.     local order=3
  134.   fi
  135.   for a in $order; do
  136.     local md5="$(eval echo \$$a)"
  137.     local siz="$(eval echo \$$(( $a+1 )))"
  138.     local typ="$(eval echo \$$(( $a+2 )))"
  139.     local from
  140.     local dest
  141.  
  142.     case "$typ" in
  143.       "bz2") from="$1.bz2"; dest="$2.bz2" ;;
  144.       "gz") from="$1.gz"; dest="$2.gz" ;;
  145.       *) from="$1"; dest="$2" ;;
  146.     esac
  147.  
  148.     info "Retrieving $from"
  149.     if ! just_get "$from" "$dest"; then return 1; fi
  150.     info "Validating $dest"
  151.     if [ "$md5" = "" ] || check_md5 $dest $md5 $siz; then
  152.       case "$typ" in
  153.         "gz") gunzip "$dest" ;;
  154.         "bz2") bunzip2 "$dest" ;;
  155.       esac
  156.       return 0
  157.     else
  158.       warning "$from was corrupt"
  159.     fi
  160.   done
  161.   return 1
  162. }
  163.  
  164. just_get () {
  165.   # args: from dest
  166.   local from="$1"
  167.   local dest="$2"
  168.   mkdir -p "${dest%/*}"
  169.   if [ "${from#null:}" != "$from" ]; then
  170.     error 1 "${from#null:} was not pre-downloaded"
  171.   elif [ "${from#http://}" != "$from" -o "${from#ftp://}" != "$from" ]; then
  172.     # http/ftp mirror
  173.     if wgetprogress -O "$dest" "$from"; then
  174.       return 0
  175.     elif [ -s "$dest" ]; then
  176.       local iters=0
  177.       while [ "$iters" -lt 3 ]; do
  178.         warning "Retrying failed download of $from"
  179.         if wgetprogress -c -O "$dest" "$from"; then break; fi
  180.         iters="$(($iters + 1))"
  181.       done
  182.     else
  183.       rm -f "$dest"
  184.       return 1
  185.     fi
  186.   elif [ "${from#file:}" != "$from" ]; then
  187.     local base="${from#file:}"
  188.     if [ "${base#//}" != "$base" ]; then
  189.       base="/${from#file://*/}"
  190.     fi
  191.     if [ -e "$base" ]; then
  192.       cp "$base" $dest
  193.       return 0
  194.     else
  195.       return 1
  196.     fi
  197.   else
  198.     error 1 "unknown location $from"
  199.   fi
  200. }
  201.  
  202. download () {
  203.     "$DOWNLOAD_DEBS" $(echo "$@" | tr ' ' '\n' | sort)
  204. }
  205.  
  206. debfor () {
  207.     "$DEBFOR" "$@"
  208. }
  209.  
  210. apt_debfor () {
  211.   for p in "$@"; do (
  212.     cd "$TARGET/var/cache/apt/archives"
  213.     local chk=0
  214.     for x in ${p}_*_*.deb; do
  215.       if [ -e "$x" ]; then
  216.         echo "/var/cache/apt/archives/$x"
  217.         chk=1
  218.       fi
  219.     done
  220.     if [ "$chk" = 0 ]; then return 1; fi
  221.   ); done
  222. }
  223.  
  224. apt_dest () {
  225.   # args:
  226.   #   deb package version arch mirror path
  227.   #   pkg suite component arch mirror path
  228.   #   rel suite mirror path
  229.   case "$1" in
  230.     "deb")
  231.       echo "var/cache/apt/archives/${2}_${3}_${4}.deb" | sed 's/:/%3a/'
  232.       ;;
  233.     "pkg")
  234.       local m="$5"
  235.       m="debootstrap.invalid"
  236.       #if [ "${m#http://}" != "$m" ]; then
  237.       #  m=${m#http://}
  238.       #elif [ "${m#file://}" != "$m" ]; then
  239.       #  m="file_localhost_${m#file://*/}"
  240.       #elif [ "${m#file:/}" != "$m" ]; then
  241.       #  m="file_localhost_${m#file:/}"
  242.       #fi
  243.  
  244.       printf "$APTSTATE/lists/"
  245.       echo "${m}_$6" | sed 's/\//_/g'
  246.       ;;
  247.     "rel")
  248.       local m="$3"
  249.       m="debootstrap.invalid"
  250.       #if [ "${m#http://}" != "$m" ]; then
  251.       #  m=${m#http://}
  252.       #elif [ "${m#file://}" != "$m" ]; then
  253.       #  m="file_localhost_${m#file://*/}"
  254.       #elif [ "${m#file:/}" != "$m" ]; then
  255.       #  m="file_localhost_${m#file:/}"
  256.       #fi
  257.       printf "$APTSTATE/lists/"
  258.       echo "${m}_$4" | sed 's/\//_/g'
  259.       ;;
  260.   esac
  261. }
  262.  
  263. ################################################################## download
  264.  
  265. get_release_md5 () {
  266.   local reldest="$1"
  267.   local path="$2"
  268.   sed -n '/^[Mm][Dd]5[Ss][Uu][Mm]/,/^[^ ]/p' < $reldest | while read a b c; do
  269.     if [ "$c" = "$path" ]; then echo "$a $b"; fi
  270.   done | head -n 1
  271. }
  272.  
  273. download_release_indices () {
  274.   local m1=${MIRRORS%% *}
  275.   local reldest="$TARGET/$($DLDEST rel $SUITE $m1 dists/$SUITE/Release)"
  276.   progress 0 100 "Downloading Release file"
  277.   progress_next 100
  278.   get "$m1/dists/$SUITE/Release" $reldest || 
  279.     error 1 "Failed getting release file $m1/dists/$SUITE/Release"
  280.  
  281.   TMPCOMPONENTS="$(sed -n 's/Components: *//p' $reldest)"
  282.   for c in $TMPCOMPONENTS ; do
  283.     case "$c" in
  284.       main|*/main)
  285.         COMPONENTS="$COMPONENTS $c"
  286.         ;;
  287.     esac    
  288.   done
  289.   
  290.   if [ "$COMPONENTS" = "" ]; then
  291.     mv $reldest "$reldest.malformed"
  292.     error 1 "Invalid Release file, no main components"
  293.   fi
  294.   progress 100 100 "Downloading Release file"
  295.  
  296.   local totalpkgs=0
  297.   for c in $COMPONENTS; do
  298.       local subpath="$c/binary-$ARCH/Packages"
  299.       local normmd="`get_release_md5 $reldest ${subpath}`"
  300.       if [ "$normmd" = "" ]; then
  301.         mv $reldest "$reldest.malformed"
  302.         error 1 "Invalid Release file, no entry for $subpath"
  303.       fi
  304.       totalpkgs="$(( $totalpkgs + ${normmd#* } ))"
  305.   done
  306.  
  307.   local donepkgs=0
  308.   progress 0 $totalpkgs "Downloading Packages files"
  309.   for c in $COMPONENTS; do
  310.     local subpath="$c/binary-$ARCH/Packages"
  311.     local path="dists/$SUITE/$subpath"
  312.     local bz2md="`get_release_md5 $reldest ${subpath}.bz2`"
  313.     local gzmd="`get_release_md5 $reldest ${subpath}.gz`"
  314.     local normmd="`get_release_md5 $reldest ${subpath}`"
  315.     local ext="$normmd ."
  316.     if [ -x /usr/bin/bunzip2 -a "$bz2md" != "" ]; then
  317.       ext="$ext $bz2md bz2"
  318.     fi
  319.     if [ -x /bin/gunzip -a "$gzmd" != "" ]; then
  320.       ext="$ext $gzmd gz"
  321.     fi
  322.     progress_next "$(($donepkgs + ${normmd#* }))"
  323.     for m in $MIRRORS; do
  324.       local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m $path)"
  325.       if get "$m/$path" "$pkgdest" $ext; then break; fi
  326.     done
  327.     donepkgs="$(($donepkgs + ${normmd#* }))"
  328.     progress $donepkgs $totalpkgs "Downloading Packages files"
  329.   done
  330. }
  331.  
  332. download_release () {
  333.   download_release_indices
  334.  
  335.   local m1=${MIRRORS%% *}
  336.  
  337.   local totaldebs=0
  338.   for p in "$@"; do
  339.     for c in $COMPONENTS; do
  340.       local path="dists/$SUITE/$c/binary-$ARCH/Packages"
  341.       local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m1 $path)"
  342.       if [ ! -e "$pkgdest" ]; then continue; fi
  343.       details="$($PKGDETAILS $p $m1 $pkgdest)"
  344.       if [ -z "$details" ]; then continue; fi
  345.       size="${details##* }"; details="${details% *}"
  346.       totaldebs="$(($totaldebs + $size))"
  347.     done
  348.   done 
  349.  
  350.   local dloaddebs=0
  351.  
  352.   progress $dloaddebs $totaldebs "Downloading packages"
  353.   for p in "$@"; do
  354.     for c in $COMPONENTS; do
  355.       local details=""
  356.       for m in $MIRRORS; do
  357.         local path="dists/$SUITE/$c/binary-$ARCH/Packages"
  358.         local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m $path)"
  359.         if [ ! -e "$pkgdest" ]; then continue; fi
  360.         details="$($PKGDETAILS $p $m $pkgdest)"
  361.         if [ -z "$details" ]; then continue; fi
  362.         size="${details##* }"; details="${details% *}"
  363.         md5="${details##* }"; details="${details% *}"
  364.     progress_next "$(($dloaddebs + $size))"
  365.         local debdest="$TARGET/$($DLDEST deb $details)"
  366.         if get "$m/${details##* }" $debdest $md5 $size; then
  367.           dloaddebs="$(($dloaddebs + $size))"
  368.           details="done"
  369.           break
  370.         fi
  371.       done
  372.       if [ "$details" != "" ]; then
  373.         break
  374.       fi
  375.     done
  376.     progress $dloaddebs $totaldebs "Downloading packages"
  377.     if [ "$details" != "done" ]; then
  378.       error 1 "Couldn't download $p"
  379.     fi
  380.   done
  381. }
  382.  
  383. download_main () {
  384.   local m1=${MIRRORS%% *}
  385.   progress 0 100 "Downloading Packages file"
  386.   progress_next 100
  387.   COMPONENTS=main
  388.   export COMPONENTS
  389.   for m in $MIRRORS; do
  390.     for c in $COMPONENTS; do
  391.       local path="dists/$SUITE/$c/binary-$ARCH/Packages"
  392.       local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m $path)"
  393.       if [ -x /bin/gunzip ] && get "$m/${path}.gz" "${pkgdest}.gz"; then
  394.         rm -f ${pkgdest}
  395.         gunzip ${pkgdest}.gz
  396.       elif get "$m/$path" "$pkgdest"; then
  397.         true
  398.       fi
  399.     done
  400.   done
  401.   progress 100 100 "Downloading Packages file"
  402.  
  403.   for p in "$@"; do
  404.     for c in $COMPONENTS; do
  405.       local details=""
  406.       for m in $MIRRORS; do
  407.         local path="dists/$SUITE/$c/binary-$ARCH/Packages"
  408.         local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m $path)"
  409.         if [ ! -e "$pkgdest" ]; then continue; fi
  410.         details="$($PKGDETAILS $p $m $pkgdest)"
  411.         if [ -z "$details" ]; then continue; fi
  412.         size="${details##* }"; details="${details% *}"
  413.         md5="${details##* }"; details="${details% *}"
  414.         local debdest="$TARGET/$($DLDEST deb $details)"
  415.         if get "$m/${details##* }" $debdest $md5 $size; then
  416.           details="done"
  417.           break
  418.         fi
  419.       done
  420.       if [ "$details" != "" ]; then
  421.         break
  422.       fi
  423.     done
  424.     if [ "$details" != "done" ]; then
  425.       error 1 "Couldn't download $p"
  426.     fi
  427.   done
  428. }
  429.  
  430. ################################################################ extraction
  431.  
  432. extract () { (
  433.   cd "$TARGET"
  434.   local p=0
  435.   for pkg in $(debfor "$@"); do
  436.     p="$(($p + 1))"
  437.     progress "$p" "$#" "Extracting packages"
  438.     info "Extracting $pkg..."
  439.     ar -p ./$pkg data.tar.gz | zcat | tar -xf -
  440.   done
  441.   sync
  442. ); }
  443.  
  444. in_target_nofail () {
  445.   if ! eval chroot "$TARGET" "$@" 2>/dev/null; then
  446.     true
  447.   fi
  448.   return 0
  449. }
  450.  
  451. in_target_failmsg () {
  452.   local msg="$1"
  453.   shift
  454.   if ! eval chroot "$TARGET" "$@"; then
  455.     warning "$msg"
  456.     return 1
  457.   fi
  458.   return 0
  459. }
  460.  
  461. in_target () {
  462.   in_target_failmsg "Failure trying to run: chroot $TARGET $*" "$@"
  463. }
  464.  
  465. ###################################################### standard setup stuff
  466.  
  467. conditional_cp () {
  468.   if [ ! -e "$2/$1" -a -e "$1" ]; then cp -a "$1" "$2/$1"; fi
  469. }
  470.  
  471. setup_etc () {
  472.   mkdir -p "$TARGET/etc"
  473.   
  474.   conditional_cp /etc/resolv.conf "$TARGET"
  475.   conditional_cp /etc/hostname "$TARGET"
  476.   
  477.   if [ "$DLDEST" = apt_dest -a ! -e "$TARGET/etc/apt/sources.list" ]; then
  478.     mkdir -p "$TARGET/etc/apt"
  479.     for m in $MIRRORS; do
  480.       local cs=""
  481.       for c in $COMPONENTS; do
  482.         local path="dists/$SUITE/$c/binary-$ARCH/Packages"
  483.         local pkgdest="$TARGET/$($DLDEST pkg $SUITE $c $ARCH $m $path)"
  484.         if [ -e "$pkgdest" ]; then cs="$cs $c"; fi
  485.       done
  486.       #if [ "$cs" != "" ]; then echo "deb $m $SUITE$cs"; fi
  487.       m="http://debootstrap.invalid/"
  488.       if [ "$cs" != "" ]; then echo "deb $m $SUITE$cs"; fi
  489.     done > "$TARGET/etc/apt/sources.list"
  490.   fi
  491. }
  492.  
  493. setup_proc () {
  494.   on_exit "umount $TARGET/proc"
  495.   umount $TARGET/proc 2>/dev/null || true
  496.   in_target mount -t proc proc /proc
  497. }
  498.  
  499. setup_devices () {
  500.   if [ -e $DEVICES_TARGZ ]; then
  501.     (cd "$TARGET"; zcat $DEVICES_TARGZ | tar -xf -)
  502.   else
  503.     if [ -e /dev/.devfsd ]; then
  504.       in_target mount -t devfs devfs /dev
  505.     else
  506.       error 1 "no $DEVICES_TARGZ. can't create devices"
  507.     fi
  508.   fi
  509. }
  510.  
  511. setup_dselect_method () {
  512.   case "$1" in
  513.     "apt")
  514.       mkdir -p "$TARGET/var/lib/dpkg"
  515.       echo "apt apt" > "$TARGET/var/lib/dpkg/cmethopt"
  516.       chmod 644 "$TARGET/var/lib/dpkg/cmethopt"
  517.       ;;
  518.     *)
  519.       error 1 "unknown dselect method"
  520.       ;;
  521.   esac
  522. }
  523.  
  524. ################################################################### helpers
  525.  
  526. repeat () {
  527.   local n="$1"
  528.   shift
  529.   while [ "$n" -gt 0 ]; do
  530.     if "$@"; then
  531.       break
  532.     else
  533.       n="$(( $n - 1 ))"
  534.       sleep 1
  535.     fi
  536.   done
  537.   if [ "$n" -eq 0 ]; then return 1; fi
  538.   return 0
  539. }
  540.  
  541. N_EXIT_THINGS=0
  542. exit_function () {
  543.   local n=0
  544.   while [ "$n" -lt "$N_EXIT_THINGS" ]; do
  545.     eval $(eval echo \${EXIT_THING_$n})
  546.     n="$(( $n + 1 ))"
  547.   done
  548.   N_EXIT_THINGS=0
  549. }
  550.  
  551. trap "exit_function" 0
  552. trap "exit 129" 1
  553. trap "error 130 \"Interrupt caught ... exiting\"" 2
  554. trap "exit 131" 3
  555. trap "exit 143" 15
  556.  
  557. on_exit () {
  558.   eval `echo EXIT_THING_${N_EXIT_THINGS}=\"$1\"`
  559.   N_EXIT_THINGS="$(( $N_EXIT_THINGS + 1 ))"
  560. }
  561.